/**
 * PackageSuite.java
 * 卢晓峰
 * Email：lxf9601@gmail.com
 * QQ：297051898
 * Created by 2010-6-6
 */
package com.autoabacus.core.test;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;

import org.junit.runners.Suite;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.RunnerBuilder;

/**
 * 测试运行套件,支持包
 * @author 卢晓峰
 */
public class PackageSuite extends Suite {

	public PackageSuite(Class<?> klass, RunnerBuilder builder) throws InitializationError, UnsupportedEncodingException {
		super(builder, klass, getAnnotatedClasses(klass));
	}

	/**
	 * 重写父类获取套件所有class方法
	 * @param klass
	 * @return
	 * @throws InitializationError
	 * @throws UnsupportedEncodingException 
	 */
	private static Class<?>[] getAnnotatedClasses(Class<?> klass) throws InitializationError, UnsupportedEncodingException {
		SuitePackageNames packageNames = klass.getAnnotation(SuitePackageNames.class);
		List<Class<?>> classList = new ArrayList<Class<?>>();
		for(String packageName : packageNames.value()){
			File file = new File(URLDecoder.decode(ClassLoader.getSystemResource(packageName.replace(".", "/")).getFile(), "utf8"));			
			if(file.exists()){
				scanTestCases(packageName, file, classList);
			}
		}
		// 转为数组
		Class<?>[] classArray = new Class<?>[classList.size()];
		for (int i = 0; i < classList.size(); i++) {
			classArray[i] = classList.get(i);
		}
		return classArray;
	}
	/**
	 * 扫描目录中的测试用例
	 * @param file 文件或目录
	 * @param classList 用例的class列表
	 */
	private static void scanTestCases(String packageName, File file, List<Class<?>> classList)	{
		if (file.isDirectory()) {
			for (File childFile : file.listFiles()) {
				scanTestCases(packageName + (packageName.charAt(packageName.length() - 1) != '.'
						? "." : "") + childFile.getName(), childFile, classList);
			}
		} else
		{
			String filename = file.getName();
			if(filename.endsWith("class")){
				filename = packageName.substring(0, packageName.lastIndexOf("."));
				try {
					Class<?> cla = Class.forName(filename);
					if(cla != null && cla.getSimpleName().lastIndexOf("Tests") != -1){
						classList.add(cla);
					}
				} catch (ClassNotFoundException e) {
					throw new RuntimeException(e);
				}
			}
		}
	}
	
	/**
	 * 以包名数组为测试套件
	 */
	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.TYPE)
	@Inherited
	public @interface SuitePackageNames {
		/**
		 * @return the classes to be run
		 */
		public String[] value();
	}
}
